package com.jilujia.web.controller;

import java.security.Principal;
import java.sql.SQLException;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;

import org.hibernate.HibernateException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.annotation.Secured;
import org.springframework.security.authentication.encoding.PasswordEncoder;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.jilujia.domain.hotel.Hotel;
import com.jilujia.domain.hotel.service.HotelService;
import com.jilujia.domain.user.User;
import com.jilujia.domain.user.service.UserService;
import com.jilujia.framework.exception.ResourceNotFoundException;
import com.jilujia.framework.security.JilujiaUser;
import com.jilujia.web.json.UserData;

@Controller
public class UsersController extends AbstractWebController {

	private static final Logger LOG = LoggerFactory.getLogger(UsersController.class);

	@Autowired
	private UserService userService;

	@Autowired
	private HotelService hotelService;

	@Autowired
	private PasswordEncoder passwordEncoder;

	// @Autowired
	// private WebApplicationContext webApplicationContext;

	public UsersController() {
	}

	@RequestMapping(value = "/users/register", method = RequestMethod.GET)
	public String showRegister(Model model) {
		model.addAttribute(userService.createUser());
		return "users/register";
	}

	@RequestMapping(value = "/users/register", method = RequestMethod.POST)
	public String registerUser(@Valid User user, BindingResult result, HttpServletRequest request) {

		String code = (String) request.getSession().getAttribute(com.google.code.kaptcha.Constants.KAPTCHA_SESSION_KEY);
		LOG.debug("code:" + code);

		if (!code.equals(user.getKaptcha())) {
			ObjectError error = new ObjectError("kaptcha", "Kaptcha not match");
			result.addError(error);
		}

		if (result.hasErrors()) {
			return "users/register";
		}

		// User newUser = new User();
		// newUser.setNickname(user.getNickname());
		// newUser.setUsername(user.getUsername());

		user = userService.registerUser(user);

		return "redirect:../users/registerdone";
	}

	@RequestMapping(value = "/users/registerdone", method = RequestMethod.GET)
	public String registerDone(Model model) {
		// model.addAttribute(userService.createUser());
		return "users/registerdone";
	}

	@RequestMapping(value = "/users/validate", method = RequestMethod.GET)
	public String validateUser(@RequestParam String confirmtoken) {
		User user = userService.validateUser(confirmtoken);
		return "redirect:../users/" + user.getId();
	}

	@RequestMapping(value = "/users", method = RequestMethod.GET)
	public String listAllUsers(Model model) {
		List<User> users = userService.findTop10Users();
		model.addAttribute(users);

		return "users/list";
	}

	@RequestMapping(value = "/users/{id}", method = RequestMethod.GET)
	public String showUserDetail(Principal currentUser, @PathVariable Long id, Model model) {

		User user = userService.findEnabledUser(id);
		if (user == null) {
			throw new ResourceNotFoundException(id);
		}

		List<Hotel> hotelList = hotelService.findUserFollowedHotelsByUserId(id);

		model.addAttribute(user);
		model.addAttribute(hotelList);

		return "users/userdetail";
	}

	@RequestMapping(value = "/users/go", method = RequestMethod.GET)
	@Secured( { "ROLE_USER" })
	public String go(Principal currentUser) {
		JilujiaUser currentRealUser = findUserByCurrentUser(currentUser);
		return "redirect:../users/" + currentRealUser.getUserId();
	}

	@RequestMapping(value = "/users/profile", method = RequestMethod.GET)
	@Secured( { "ROLE_USER" })
	public String showUserProfile(Principal currentUser, Model model) {
		model.addAttribute(userService.findEnabledUserByUsername(currentUser.getName()));
		return "users/profile";
	}

	@RequestMapping(value = "/users/profile", method = RequestMethod.POST)
	@Secured( { "ROLE_USER" })
	public String updateUserProfile(Principal currentUser, User user, BindingResult result) throws HibernateException,
			SQLException {
		LOG.debug("user:" + user.getId());
		LOG.debug("password:" + user.getPassword());
		LOG.debug("version:" + user.getVersion());

		User existedUser = userService.findEnabledUserByUsername(currentUser.getName());
		if (!existedUser.getVersion().equals(user.getVersion())) {
			ObjectError error = new ObjectError("version", "version wrong");
			result.addError(error);
		}

		if (result.hasErrors()) {
			return "/users/profile";
		}

		String newpassword = passwordEncoder.encodePassword(user.getPassword(), null);
		LOG.debug("new password:{}", newpassword);
		existedUser.setNickname(user.getNickname());
		existedUser.setPassword(newpassword);

		user = userService.updateUserProfile(existedUser);

		// 直接清了上下问，现在需要重新登录了
		SecurityContextHolder.clearContext();
		// 下面这段是重新登录，可以看看JdbcUserDetailsManager的changepassword
		// SecurityContextHolder.getContext().setAuthentication(createNewAuthentication(currentUserS, newPassword));
		return "redirect:../users/" + user.getId();
	}

	@RequestMapping(value = "/users/get_new", method = RequestMethod.POST)
	@Secured( { "ROLE_USER" })
	public @ResponseBody
	UserData getNewMessage(Principal currentUser, @RequestParam int time) throws InterruptedException {
		LOG.debug("getNewMessage:" + time);
		JilujiaUser currentRealUser = findUserByCurrentUser(currentUser);
		LOG.debug("currentRealUser:" + currentRealUser.getUsername());

		int i = 0;
		while (true) {

			Thread.sleep(1000);// 1秒
			i++;

			// 若得到数据则马上返回数据给客服端，并结束本次请求
			// //
			double random = Math.random();
			LOG.debug("i:" + i + ":" + random);
			int rand = (int) (random * 100) + 1;

			LOG.debug("rand:" + rand);
			if (rand <= 15) {
				UserData data = new UserData();
				data.setSuccess("1");
				data.setName("test 1");
				data.setText("test data:" + rand);

				return data;
			}

			// 服务器($_POST['time']*0.5)秒后告诉客服端无数据
			if (i == time) {
				UserData data = new UserData();
				data.setSuccess("0");
				data.setName("test 2");
				data.setText("no test data");

				return data;
			}

		}
	}
}
